﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace HA.ModFlow.Domain.DomainLayer
{
    public static class BudReader
    {
        //注意： 这两个方法都有用 不要删除  区别在于第二个参数
        //第一个方法的第二个参数： List<int[,]> IBound，目前具体使用时传进来的是主程序的IBound信息
        //第二个方法的第二个参数： List<List<int[,]>> IBound ,目前具体使用时传进来的是读取项目计算完毕后从文件中读取的个各应力期的IBound数据


        public static List<BudFile> ReadBudFile(string filename, List<int[,]> IBound, string label)
        {
            if (System.IO.File.Exists(filename) == false) return null;

            List<BudFile> budLst = new List<BudFile>();

            FileStream fs = File.Open(filename, FileMode.Open);
            BinaryReader reader = new BinaryReader(fs); // '打开要读取的文件

            reader.BaseStream.Position = 0;

            if (reader.BaseStream.Length == 0) return null;

            try
            {
                //while (reader.PeekChar() != -1)
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    BudFile budObj = new BudFile();

                    // '读取文件头信息，供36字节
                    budObj.KSTP = reader.ReadInt32();   //'时间不长
                    budObj.KPER = reader.ReadInt32();   //'应力期
                    budObj.TEXT = reader.ReadChars(16);  //'标识符
                    budObj.NCOL = reader.ReadInt32();  //'列
                    budObj.NROW = reader.ReadInt32();  //'行          
                    budObj.ILAY = reader.ReadInt32();  //'层

                    // '读取实际数据 字节数=NCOL * NROW*4
                    double[, ,] values = new double[budObj.NROW, budObj.NCOL, budObj.ILAY];
                    for (int i = 0; i < budObj.ILAY; i++)
                    {
                        for (int j = 0; j < budObj.NROW; j++)
                        {
                            for (int k = 0; k < budObj.NCOL; k++)
                            {
                                values[j, k, i] = reader.ReadSingle();
                            }
                        }
                    }

                    budObj.Data = new Infrastructure.CellCenterDataSet3d(values, IBound);
                    budObj.Data.Label = label;

                    budLst.Add(budObj);
                }

                fs.Close();
                fs.Dispose();
                reader.Close();
                reader.Dispose();

                return budLst;

            }
            catch (Exception ex)
            {
                fs.Close();
                fs.Dispose();
                reader.Close();
                reader.Dispose();

                return null;
            }

        }



        public static List<BudFile> ReadBudFile(string filename,  List<List<int[,]>> IBound, string label)
        {
            if (System.IO.File.Exists(filename) == false) return null;

            if (IBound ==null )
            {
                return null;
            }


            List<BudFile> budLst = new List<BudFile>();

            FileStream fs = File.Open(filename, FileMode.Open);
            BinaryReader reader = new BinaryReader(fs); // '打开要读取的文件

            reader.BaseStream.Position = 0;

            if (reader.BaseStream.Length == 0) return null;

            try
            {
                //while (reader.PeekChar() != -1)


                //这里关于使用个各应力期IBound有一个麻烦，因为evt.bud和lpf.bud，bcf.bud等的文件中包含的数据个数不一致，例如：bcf.bud中可能包含5个文件数据
                //由于这一块的内容不是我负责的，所以对其文件结构不是很清楚，暂时想到的方案时根据 budObj.TEXT 判断，此处文件是按照应力期顺序输出，首先走
                //应力期，每个应力期循环各个文件，另外一个思路是使用 budObj.KPER ，但是就我目前对模型的理解而言，还是觉得TEXT比较靠谱


                int index = 0;//使用的  IBound 中的索引
                int readNum = 0;

                string firstText = "";//记录读取的第一个文件的text标志
                string newText = "";//记录新读取的 budObj.TEXT 标志

                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    BudFile budObj = new BudFile();

                    // '读取文件头信息，供36字节
                    budObj.KSTP = reader.ReadInt32();   //'时间不长
                    budObj.KPER = reader.ReadInt32();   //'应力期
                    budObj.TEXT = reader.ReadChars(16);  //'标识符
                    budObj.NCOL = reader.ReadInt32();  //'列
                    budObj.NROW = reader.ReadInt32();  //'行          
                    budObj.ILAY = reader.ReadInt32();  //'层

                    if (label.Trim ()=="lpf"||label.Trim ()=="bcf")
                    {
                        if (readNum == 0)
                        {
                            //while中第一次循环

                            if (index == 0)
                            {
                                //firstText = budObj.TEXT.ToString().Trim();//记录读取的第一个文件的text标志

                                firstText = new string(budObj.TEXT).Trim();//记录读取的第一个文件的text标志
                            
                            }
                        }                       
                    }

                    if (label.Trim() == "lpf" || label.Trim() == "bcf")
                    {
                        newText = new string(budObj.TEXT).Trim();//记录本次读取的文件的text标志

                        if (readNum > 0 && firstText == newText)
                        {

                            //又一次轮到了同一个文件
                            index = index + 1;//表示应力期的IBound应该+1了
                        }


                        readNum = readNum + 1;

                    }
                             

                    // '读取实际数据 字节数=NCOL * NROW*4
                    double[, ,] values = new double[budObj.NROW, budObj.NCOL, budObj.ILAY];
                    for (int i = 0; i < budObj.ILAY; i++)
                    {
                        for (int j = 0; j < budObj.NROW; j++)
                        {
                            for (int k = 0; k < budObj.NCOL; k++)
                            {
                                values[j, k, i] = reader.ReadSingle();
                            }
                        }
                    }

                    //budObj.Data = new Infrastructure.CellCenterDataSet3d(values, IBound);

                    //if (index > IBound.Count - 1)
                    //{
                    //    budObj.Data = new Infrastructure.CellCenterDataSet3d(values, IBound[IBound.Count - 1]);
                    //}
                    //else
                    //{
                        budObj.Data = new Infrastructure.CellCenterDataSet3d(values, IBound[index]);
                    //}


                    budObj.Data.Label = label;



                    budLst.Add(budObj);

                    if (label.Trim() == "lpf" || label.Trim() == "bcf")
                    {
                       
                    }
                    else
                    {
                        index = index + 1;
                    }
                   
                }

                fs.Close();
                fs.Dispose();
                reader.Close();
                reader.Dispose();

                return budLst;

            }
            catch (Exception ex)
            {
                fs.Close();
                fs.Dispose();
                reader.Close();
                reader.Dispose();

                return null;
            }

        }

    }
}
